		TITLE	ALIGN - Copyright (c) SLR Systems 1994

		INCLUDE	MACROS
		INCLUDE	SEGMENTS
		INCLUDE	GROUPS
		INCLUDE	SECTIONS
		INCLUDE	MODULES
if	fg_pe
		INCLUDE	PE_STRUC
endif

		PUBLIC	ALIGN_SEGMENTS,DO_ECX_ALIGN,SET_GROUPS

if	fg_rom

		PUBLIC	ALIGN_SEGMENT

endif

		.DATA

		EXTERNDEF	SEGMENT_NUMBER:DWORD,FIRST_GROUP_GINDEX:DWORD,LAST_GROUP_GINDEX:DWORD,FIRST_SEGMENT_GINDEX:DWORD
		EXTERNDEF	CURN_SEGMOD_GINDEX:DWORD,SEG_PAGE_SIZE_M1:DWORD,CURN_SECTION_GINDEX:DWORD,FIRST_STACK_GINDEX:DWORD
		EXTERNDEF	FIRST_FINAL_SEGMENT_GINDEX:DWORD,TD_COUNT_CSEGS:DWORD,NOT_SEG_PAGE_SIZE_M1:DWORD,PE_BASE:DWORD
		EXTERNDEF	HIGH_PC:DWORD,FIXUPP_COUNT:DWORD,STACK_SIZE:DWORD,PE_OBJECT_ALIGN:DWORD,PE_NEXT_OBJECT_RVA:DWORD
		EXTERNDEF	FIRST_AREA_GINDEX:DWORD

		EXTERNDEF	AREA_GARRAY:STD_PTR_S,SECTION_GARRAY:STD_PTR_S,GROUP_GARRAY:STD_PTR_S,SEGMENT_GARRAY:STD_PTR_S
		EXTERNDEF	SEGMOD_GARRAY:STD_PTR_S,CSEG_GARRAY:STD_PTR_S,PE_OBJECT_GARRAY:STD_PTR_S


		.CODE	MIDDLE_TEXT

		EXTERNDEF	ERR_ASCIZ_RET:PROC,SAY_VERBOSE:PROC,_err_abort:proc,ERR_RET:PROC,DO_OBJECT_ALIGN:PROC

		EXTERNDEF	SEG_TOO_BIG_ERR:ABS,TOO_MANY_BASES_ERR:ABS,STACK_NZERO_ERR:ABS

		;ES:DI = CURSEG
		;DS:SI = SEGMOD
		;DX:CX = PC

ALIGN_SEGMENTS	PROC
		;
		;
		;
		MOV	EAX,OFF ALIGN_SEGS_MSG
		CALL	SAY_VERBOSE

		MOV	ESI,FIRST_AREA_GINDEX
		XOR	ECX,ECX		;PC = 0L

		MOV	LAST_GROUP_GINDEX,ECX
		MOV	SEGMENT_NUMBER,ECX

if	fg_td
		MOV	TD_COUNT_CSEGS,ECX
endif
;		JMP	AREA_LOOP	;AT LEAST ONE AREA...

AREA_LOOP:
		CONVERT	ESI,ESI,AREA_GARRAY
		ASSUME	ESI:PTR AREA_STRUCT

		MOV	[ESI]._AREA_BASE_ADDRESS,ECX
		MOV	EDX,[ESI]._AREA_FIRST_SECT_GINDEX

		MOV	[ESI]._AREA_MAX_ADDRESS,ECX

		TEST	EDX,EDX
		JZ	END_OF_AREA
SECTION_LOOP:
		MOV	EBX,EDX
SECTION_LOOP_2:
		CONVERT	EDX,EDX,SECTION_GARRAY
		ASSUME	EDX:PTR SECTION_STRUCT

		MOV	EDI,[EDX]._SECT_PARENT_AREA_GINDEX
		MOV	CURN_SECTION_GINDEX,EBX

		CONVERT	EDI,EDI,AREA_GARRAY
		ASSUME	EDI:PTR AREA_STRUCT

		MOV	ECX,[EDI]._AREA_BASE_ADDRESS

		MOV	[EDX]._SECT_BASE_ADDRESS,ECX
		CALL	ALIGN_SECTION		;ASSIGN REAL ADDRESS TO ALL SEGMODS THIS SECTION
		;
		;IF NOT DEBUG INFO, UPDATE HIGH_PC
		;
		JNZ	L6$

		MOV	ESI,[EDX]._SECT_FIRST_AREA_GINDEX
		MOV	HIGH_PC,ECX
		;
		;SEE IF ANY NESTED - AREAS
		;
		TEST	ESI,ESI
		JNZ	AREA_LOOP
L4$:
		;
		;SET MY PARENT AREA'S MAXIMUM ADDRESS
		;
		MOV	EDI,[EDX]._SECT_PARENT_AREA_GINDEX
		CONVERT	EDI,EDI,AREA_GARRAY
		ASSUME	EDI:PTR AREA_STRUCT

		CMP	[EDI]._AREA_MAX_ADDRESS,ECX
		JA	L95$

		MOV	[EDI]._AREA_MAX_ADDRESS,ECX
L95$:
		;
		;TRY ANOTHER SECTION
		;
		MOV	ESI,[EDX]._SECT_PARENT_AREA_GINDEX
		MOV	EDX,[EDX]._SECT_NEXT_SECT_GINDEX

		TEST	EDX,EDX
		JNZ	SECTION_LOOP
		;
		;NO MORE SECTIONS, TRY ANOTHER AREA
		;
		CONVERT	ESI,ESI,AREA_GARRAY
		ASSUME	ESI:PTR AREA_STRUCT

if	fg_plink
		MOV	AX,[SI]._AREA_FORCE_SIZE.LW
		OR	AX,[SI]._AREA_FORCE_SIZE.HW
		JZ	97$
		MOV	AX,[SI]._AREA_BASE_ADDRESS.LW
		MOV	DX,[SI]._AREA_BASE_ADDRESS.HW
		ADD	AX,[SI]._AREA_FORCE_SIZE.LW
		ADC	DX,[SI]._AREA_FORCE_SIZE.HW
		ADD	AX,15
		ADC	DX,0
		AND	AL,0F0H
		MOV	[SI]._AREA_MAX_ADDRESS.LW,AX
		MOV	[SI]._AREA_MAX_ADDRESS.HW,DX
97$:
endif
		MOV	ECX,[ESI]._AREA_MAX_ADDRESS
END_OF_AREA:
		MOV	EDX,[ESI]._AREA_PARENT_SECT_GINDEX
		MOV	ESI,[ESI]._AREA_NEXT_AREA_GINDEX

		TEST	ESI,ESI
		JNZ	AREA_LOOP
		;
		;NO MORE AREAS, UPDATE PARENT SECTION (IF THERE IS ONE)
		;
		TEST	EDX,EDX
		JZ	L6$			;END OF ALIGNS...
		CONVERT	EDX,EDX,SECTION_GARRAY
		JMP	L4$

L6$:
		CALL	SIZE_SEGMENTS

		CALL	SIZE_ASEG_SEGMENTS
		;
		CALL	FIX_GROUPS

		RET

ALIGN_SEGMENTS	ENDP


ALIGN_SECTION	PROC	NEAR
		;
		;EDX IS SECTION, ALIGN ALL ASSIGNED SEGMODS.
		;
		ASSUME	EDX:PTR SECTION_STRUCT

		XOR	EAX,EAX
		MOV	ESI,[EDX]._SECT_FIRST_SEGMOD_GINDEX

		MOV	FIXUPP_COUNT,EAX		;ZERO FIXUPP COUNT FOR THIS SECTION
		MOV	EBX,ESI

		TEST	ESI,ESI
		JZ	L99$			;NO MORE SEGMODS

		MOV	CURN_SEGMOD_GINDEX,ESI
		CONVERT	ESI,ESI,SEGMOD_GARRAY
		ASSUME	ESI:PTR SEGMOD_STRUCT
		MOV	AL,[ESI]._SM_FLAGS

		TEST	AL,MASK SEG_CV_TYPES1 + MASK SEG_CV_SYMBOLS1
		JZ	L11$

		RET

L99$:
		JMP	L9$

STACK_TYPE:
		;
		;SPECIAL ALIGNMENT FOR FIRST SEGMOD OF STACK IF DOSSEG
		;
		CALL	ALIGN_STACK
		JMP	COMMON_CONTINUE

L1$:
		MOV	CURN_SEGMOD_GINDEX,ESI
		CONVERT	ESI,ESI,SEGMOD_GARRAY
L11$:
if	fg_td
		;
		;IF TD_FLAG, AND CSEGS EXISTS, UPDATE CSEG_SEG_INDEX...
		;
		TEST	[SI]._SM_FLAGS_2,MASK SM2_CSEG_DONE
		JZ	12$
		BITT	TD_FLAG
		JZ	12$
		MOV	AX,[SI]._SM_MODULE_CSEG_GINDEX
		CONVERT_GINDEX_AX_ESDI	CSEG_GARRAY
		MOV	AX,TD_COUNT_CSEGS
		INC	AX
		MOV	TD_COUNT_CSEGS,AX
		MOV	ES:[DI]._CSEG_TD_SEG_INDEX,AX
12$:

endif
		;
		;IF FIRST SEGMOD OR LOWER THAN BASE, STORE NEW BASE
		;
		MOV	EAX,[ESI]._SM_RELOC_CNT
		MOV	EBX,FIXUPP_COUNT

		MOV	EDI,[ESI]._SM_BASE_SEG_GINDEX
		ADD	EAX,EBX
		CONVERT	EDI,EDI,SEGMENT_GARRAY
		ASSUME	EDI:PTR SEGMENT_STRUCT


		MOV	EBX,[EDI]._SEG_OFFSET
		MOV	FIXUPP_COUNT,EAX
		;
		;IF THIS IS FIRST REFERENCE TO SEGMENT, MAYBE DO MAX_ALIGN, MAYBE ASSIGN OS/2 NUMBER
		;
		INC	EBX
		JNZ	L19$

		CALL	FIX_SEGMENT_NUMBER	;ASSIGN ADDRESS, SEGMENT #,  INCREMENT IF NOT IN A GROUP
L19$:
		MOV	BL,[EDI]._SEG_COMBINE
		MOV	AL,[ESI]._SM_ALIGN

		CMP	BL,SC_COMMON
		JZ	COMMON_TYPE		;COMMONS ARE SPECIAL...

		CMP	BL,SC_STACK
		JZ	STACK_TYPE
L2$:
		CALL	DO_ECX_ALIGN
if	any_overlays
		;
		;CHECK LOWEST BASE ADDRESS
		;
		CMP	ES:[DI]._SEG_OFFSET.HW,DX
		JB	33$
		JA	32$
		CMP	ES:[DI]._SEG_OFFSET.LW,CX
		JA	32$
33$:
endif
		MOV	EAX,[ESI]._SM_LEN
		MOV	[ESI]._SM_START,ECX

		ADD	ECX,EAX

		MOV	[ESI]._SM_LEN,ECX

if	any_overlays
		;
		;NOW DEFINE SEGMENT'S MAXIMUM ADDRESS
		;
		CMP	ES:[DI]._SEG_LEN.HW,DX
		JB	34$
		JA	35$
		CMP	ES:[DI]._SEG_LEN.LW,CX
		JAE	35$
34$:
endif
		MOV	[EDI]._SEG_LEN,ECX		;FOR NOW SEG_LEN IS MAX ADDRESS
;L35$:
		MOV	ESI,[ESI]._SM_NEXT_SEGMOD_GINDEX
COMMON_CONTINUE::
		TEST	ESI,ESI
		JNZ	L1$
		;
		ADD	ECX,15		;AT LEAST PARAGRAPH ALIGNED...

		AND	ECX,-16
L9$:
		JMP	END_OF_SECTION

if	any_overlays
32$:
		MOV	ES:[DI]._SEG_OFFSET.LW,CX
		MOV	ES:[DI]._SEG_OFFSET.HW,DX
		JMP	33$
endif

ALIGN_SECTION	ENDP


COMMON_TYPE	PROC	NEAR
		;
		;HANDLE A COMMON
		;
		;NOW SCAN ALL SEGMODS THIS COMMON-BLOCK, DEFINING START ADDR,
		;END-ADDR, AND MAX ADDRESS
		;
		PUSH	EBP
		XOR	EDX,EDX

		MOV	EBX,FIXUPP_COUNT
		MOV	EDI,[ESI]._SM_BASE_SEG_GINDEX

		JMP	L51$

L5$:
		ADD	EBX,[ESI]._SM_RELOC_CNT
L51$:
		MOV	EAX,[ESI]._SM_LEN
		MOV	[ESI]._SM_START,ECX

		ADD	EAX,ECX
		;
		CMP	EDX,EAX
		JAE	L54$
L53$:
		MOV	EDX,EAX
L54$:
		MOV	EBP,[ESI]._SM_NEXT_SEGMOD_GINDEX
		MOV	[ESI]._SM_LEN,EAX

		MOV	ESI,EBP

		TEST	EBP,EBP
		JZ	L6$

		CONVERT	ESI,ESI,SEGMOD_GARRAY
		ASSUME	ESI:PTR SEGMOD_STRUCT

		CMP	[ESI]._SM_BASE_SEG_GINDEX,EDI
		JZ	L5$
L6$:
		CONVERT	EDI,EDI,SEGMENT_GARRAY
		ASSUME	EDI:PTR SEGMENT_STRUCT

		MOV	[EDI]._SEG_LEN,EDX
		MOV	ESI,EBP

		MOV	FIXUPP_COUNT,EBX
		POP	EBP

		MOV	ECX,EDX
		JMP	COMMON_CONTINUE

COMMON_TYPE	ENDP


ALIGN_STACK	PROC	NEAR
		;
		;ESI IS SEGMOD, EDI IS SEGMENT, ECX IS ADDRESS, AL IS FIRST ALIGNMENT TYPE
		;
		;SCAN SEGMODS, ADD UP TOTAL SIZE, THEN ASSIGN EACH TO END OF STACK-SPACE
		;
		BITT	DOSSEG_FLAG
		JZ	L1$

		CMP	AL,3
		JZ	L1$

		CMP	AL,4
		JZ	L1$

		MOV	AL,3
L1$:
		CALL	DO_ECX_ALIGN

		PUSH	ECX
		MOV	ECX,[ESI]._SM_LEN

		MOV	EDI,[ESI]._SM_BASE_SEG_GINDEX
		MOV	EBX,FIXUPP_COUNT

L2$:
		MOV	ESI,[ESI]._SM_NEXT_SEGMOD_GINDEX

		TEST	ESI,ESI
		JZ	L3$

		CONVERT	ESI,ESI,SEGMOD_GARRAY
		ASSUME	ESI:PTR SEGMOD_STRUCT

		MOV	EDX,[ESI]._SM_BASE_SEG_GINDEX
		MOV	EAX,[ESI]._SM_RELOC_CNT

		CMP	EDX,EDI
		JNZ	L3$

		MOV	EDX,[ESI]._SM_LEN
		ADD	EBX,EAX

		ADD	ECX,EDX
		JMP	L2$

L3$:
		MOV	ESI,EDI
		MOV	FIXUPP_COUNT,EBX

		GETT	AL,OUTPUT_PE

		OR	AL,AL
		JNZ	L4$

		;
		;DX:CX IS TOTAL SIZE OF THIS STACK SEGMENT
		;
		GETT	AL,STACK_SIZE_FLAG

		OR	AL,AL
		JZ	L4$

		CMP	FIRST_STACK_GINDEX,EDI
		JNZ	L4$

		MOV	ECX,STACK_SIZE
L4$:
		;
		;SET STUFF FOR MASTER SEGMENT
		;
		CONVERT	ESI,ESI,SEGMENT_GARRAY
		ASSUME	ESI:PTR SEGMENT_STRUCT

		POP	EAX

		MOV	[ESI]._SEG_OFFSET,EAX
		ADD	ECX,EAX

		MOV	[ESI]._SEG_LEN,ECX
		;
		;NOW, FOR EACH PIECE, SET START AND STOP
		;
		MOV	ESI,CURN_SEGMOD_GINDEX
L5$:
		MOV	EBX,ESI
		CONVERT	ESI,ESI,SEGMOD_GARRAY
		ASSUME	ESI:PTR SEGMOD_STRUCT
		MOV	EAX,[ESI]._SM_BASE_SEG_GINDEX

		CMP	EAX,EDI
		JNZ	L6$

		MOV	EAX,ECX
		MOV	EBX,[ESI]._SM_LEN

		MOV	[ESI]._SM_LEN,ECX
		SUB	EAX,EBX

		MOV	[ESI]._SM_START,EAX
		MOV	ESI,[ESI]._SM_NEXT_SEGMOD_GINDEX

		TEST	ESI,ESI
		JNZ	L5$

		RET

L6$:
		MOV	EAX,EBX
		RET

ALIGN_STACK	ENDP


END_OF_SECTION	PROC	NEAR
		;
		;END OF SECTION, UPDATE PARENT SECTION
		;
		GETT	AL,OUTPUT_PE

		OR	AL,AL
		JZ	L1$

		MOV	ESI,CURN_PEOBJECT_GINDEX
		CONVERT	ESI,ESI,PE_OBJECT_GARRAY
		ASSUME	ESI:PTR PE_OBJECT_STRUCT

		MOV	EAX,ECX

		DO_FILE_ALIGN_EAX

		MOV	EBX,EAX
		MOV	ECX,PE_BASE

		SUB	EBX,ECX
		MOV	ECX,[ESI]._PEOBJECT_RVA

		SUB	EBX,ECX

		MOV	[ESI]._PEOBJECT_VSIZE,EBX
		CALL	DO_OBJECT_ALIGN

		MOV	ECX,EAX
		SUB	EAX,PE_BASE

		MOV	PE_NEXT_OBJECT_RVA,EAX
L1$:

		MOV	EDX,CURN_SECTION_GINDEX
		CONVERT	EDX,EDX,SECTION_GARRAY
		ASSUME	EDX:PTR SECTION_STRUCT

		MOV	EAX,FIXUPP_COUNT

		MOV	[EDX]._SECT_MAX_ADDRESS,ECX
		MOV	[EDX]._SECT_RELOCS,EAX

		CMP	EAX,64K
		JAE	L9$

		CMP	EAX,EAX			;SET ZERO FLAG

		RET

L9$:
		MOV	AL,TOO_MANY_BASES_ERR
		push	EAX
		call	_err_abort

END_OF_SECTION	ENDP


SIZE_SEGMENTS	PROC	NEAR
		;
		;OK, NOW UPDATE BASE SEGMENT OVERALL LENGTH AND FRAME IF REAL-MODE
		;
		MOV	EDX,FIRST_SEGMENT_GINDEX
		JMP	L8$

L1$:
		CONVERT	ESI,ESI,SEGMENT_GARRAY
		ASSUME	ESI:PTR SEGMENT_STRUCT

		MOV	AL,[ESI]._SEG_TYPE
		MOV	EDX,[ESI]._SEG_NEXT_SEG_GINDEX

		TEST	AL,MASK SEG_CV_TYPES1 + MASK SEG_CV_SYMBOLS1
		JNZ	L3$

		MOV	ECX,[ESI]._SEG_OFFSET
		MOV	EBX,[ESI]._SEG_LEN

		SUB	EBX,ECX
		MOV	EDI,ECX

		MOV	[ESI]._SEG_LEN,EBX
		GETT	AL,OUTPUT_PE

		TEST	AL,AL
		JNZ	L8$
		;
		;VERIFY SEGMENT <= 64K
		;
		AND	ECX,0FH

		ADD	ECX,EBX

		CMP	ECX,64K
		JA	L5$
		;
		;IF REAL MODE, SET FRAME
		;
L2$:
if	fg_segm
		GETT	AL,OUTPUT_SEGMENTED

		TEST	AL,AL
		JNZ	L8$
endif
		AND	EDI,0FFFFFFF0H

		MOV	[ESI]._SEG_FRAME,EDI
L8$:
		MOV	ESI,EDX

		TEST	EDX,EDX
		JNZ	L1$

		RET

L3$:
		XOR	EBX,EBX
		MOV	[ESI]._SEG_OFFSET,EBX
		MOV	[ESI]._SEG_LEN,EBX
		MOV	[ESI]._SEG_FRAME,EBX
		JMP	L8$

L5$:
		MOV	AL,[ESI]._SEG_32FLAGS

		TEST	AL,MASK SEG32_USE32	;WHO CARES IF ITS A 32-BIT SEGMENT...
		JNZ	L2$

		PUSH	ECX
		LEA	ECX,[ESI]._SEG_TEXT
		MOV	AL,SEG_TOO_BIG_ERR
		CALL	ERR_ASCIZ_RET
		POP	ECX
		JMP	L2$

SIZE_SEGMENTS	ENDP


SIZE_ASEG_SEGMENTS	PROC	NEAR
		;
		;OK, NOW UPDATE BASE SEGMENT OVERALL LENGTH AND FRAME IF REAL-MODE
		;
		MOV	EAX,FIRST_FINAL_SEGMENT_GINDEX

		TEST	EAX,EAX
		JZ	L9$
L1$:
		MOV	EBX,EAX
		CONVERT	EAX,EAX,SEGMENT_GARRAY
		ASSUME	EAX:PTR SEGMENT_STRUCT

		MOV	EAX,[EAX]._SEG_FIRST_SEGMOD_GINDEX
		XOR	ECX,ECX
L2$:
		TEST	EAX,EAX
		JZ	L5$

		CONVERT	EAX,EAX,SEGMOD_GARRAY
		ASSUME	EAX:PTR SEGMOD_STRUCT

		MOV	EDX,[EAX]._SM_LEN
		MOV	EAX,[EAX]._SM_NEXT_SEGMOD_GINDEX

		CMP	ECX,EDX
		JA	L2$

		MOV	ECX,EDX
		JMP	L2$

L5$:
		CONVERT	EBX,EBX,SEGMENT_GARRAY
		ASSUME	EBX:PTR SEGMENT_STRUCT

		MOV	EDX,[EBX]._SEG_OFFSET
		MOV	EAX,[EBX]._SEG_NEXT_SEG_GINDEX

		SUB	ECX,EDX
		TEST	EAX,EAX

		MOV	[EBX]._SEG_LEN,ECX
		JNZ	L1$
L9$:
		RET

SIZE_ASEG_SEGMENTS	ENDP


SET_GROUPS	PROC
		;
		;SET FIRST AND LAST SEGMENTS IN GROUPS BASED ON LOGICAL SEGMENT ORDER
		;
		MOV	EAX,FIRST_GROUP_GINDEX
		XOR	EDX,EDX

		TEST	EAX,EAX
		JZ	SEGS_DONE
		;
		;FIRST, CLEAR OUT FIRST AND LAST SEGMENT ENTRIES
		;
L1$:
		CONVERT	EAX,EAX,GROUP_GARRAY
		ASSUME	EAX:PTR GROUP_STRUCT

		MOV	[EAX]._G_FIRST_SEG_GINDEX,EDX
		MOV	[EAX]._G_LAST_SEG_GINDEX,EDX

		MOV	EAX,[EAX]._G_NEXT_GROUP_GINDEX

		TEST	EAX,EAX
		JNZ	L1$
		;
		;THEN SCAN SEGMENTS TO REDEFINE FIRST AND LAST SEGMENTS BASED ON ORDER
		;
		MOV	ESI,FIRST_SEGMENT_GINDEX
TEST_SEGMENT:
		TEST	ESI,ESI
		JZ	SEGS_DONE

		MOV	EDX,ESI
		CONVERT	ESI,ESI,SEGMENT_GARRAY
		ASSUME	ESI:PTR SEGMENT_STRUCT

		MOV	EDI,[ESI]._SEG_GROUP_GINDEX
		MOV	ESI,[ESI]._SEG_NEXT_SEG_GINDEX

		TEST	EDI,EDI
		JZ	TEST_SEGMENT

		CONVERT	EDI,EDI,GROUP_GARRAY
		ASSUME	EDI:PTR GROUP_STRUCT

		MOV	EAX,[EDI]._G_FIRST_SEG_GINDEX
		MOV	[EDI]._G_LAST_SEG_GINDEX,EDX

		TEST	EAX,EAX
		JNZ	TEST_SEGMENT

		MOV	[EDI]._G_FIRST_SEG_GINDEX,EDX
		JMP	TEST_SEGMENT

SEGS_DONE:
		RET

SET_GROUPS	ENDP


FIX_GROUPS	PROC
		;
		;SET FIRST AND LAST SEGMENTS IN GROUPS BASED ON PHYSICAL ADDRESS (WITH OVERLAYS, THIS MAY BE DIFFERENT)
		;
		MOV	EAX,FIRST_GROUP_GINDEX
		XOR	EDX,EDX

		TEST	EAX,EAX
		JZ	SEGS_DONE
		;
		;FIRST, CLEAR FIRST AND LAST SEGMENT ENTRIES
		;
L1$:
		CONVERT	EAX,EAX,GROUP_GARRAY
		ASSUME	EAX:PTR GROUP_STRUCT

		MOV	[EAX]._G_FIRST_SEG_GINDEX,EDX
		MOV	[EAX]._G_LAST_SEG_GINDEX,EDX

		MOV	EAX,[EAX]._G_NEXT_GROUP_GINDEX

		TEST	EAX,EAX
		JNZ	L1$
		;
		;SET FIRST AND LAST SEGMENTS IN GROUPS, THEN SCAN GROUPS
		;FOR LENGTH VIOLATIONS
		;
		MOV	ESI,FIRST_SEGMENT_GINDEX
TEST_SEGMENT:
		TEST	ESI,ESI
		JZ	SEGS_DONE

		MOV	EDX,ESI
		CONVERT	ESI,ESI,SEGMENT_GARRAY
		ASSUME	ESI:PTR SEGMENT_STRUCT
		MOV	EDI,[ESI]._SEG_GROUP_GINDEX

		MOV	EBX,ESI
		MOV	ESI,[ESI]._SEG_NEXT_SEG_GINDEX

		TEST	EDI,EDI
		JZ	TEST_SEGMENT
		;
		;SEGMENT BELONGS TO A GROUP
		;
		CONVERT	EDI,EDI,GROUP_GARRAY
		ASSUME	EDI:PTR GROUP_STRUCT

		MOV	EAX,[EDI]._G_FIRST_SEG_GINDEX
		MOV	[EDI]._G_LAST_SEG_GINDEX,EDX

		TEST	EAX,EAX
		JZ	DO_G_FIRST_SEG
DGFS_RET:
		ASSUME	ESI:NOTHING,EBX:PTR SEGMENT_STRUCT
		;
		;NOW UPDATE GROUP FRAME AND LEN
		;
		MOV	ECX,[EBX]._SEG_OFFSET		;IS THIS OFFSET LOWER THAN BEFORE?
		MOV	EAX,[EDI]._G_OFFSET

		CMP	EAX,ECX
		JBE	L3$

		MOV	[EDI]._G_OFFSET,ECX

if	fg_segm OR fg_pe

		GETT	AL,OUTPUT_SEGMENTED
		GETT	DL,OUTPUT_PE

		OR	AL,DL
		JNZ	L3$
endif

		MOV	EAX,ECX			;IF REAL-MODE, SET FRAME

		AND	AL,0F0H

		MOV	[EDI]._G_FRAME,EAX
L3$:
		;
		;NOW UPDATE GROUP LEN
		;
		MOV	EAX,[EBX]._SEG_LEN
		MOV	EBX,[EDI]._G_LEN

		ADD	ECX,EAX

		CMP	EBX,ECX
		JAE	L5$

		MOV	[EDI]._G_LEN,ECX
L5$:
		JMP	TEST_SEGMENT

SEGS_DONE:
		RET

DO_G_FIRST_SEG:
		MOV	[EDI]._G_FIRST_SEG_GINDEX,EDX
		JMP	DGFS_RET

FIX_GROUPS	ENDP


DO_ECX_ALIGN	PROC
		;
		;
		;
		AND	EAX,7

		ADD	ECX,COM_TABLE[EAX*8]

		AND	ECX,COM_TABLE[EAX*8+4]

L1$:
		RET

DO_ECX_ALIGN	ENDP


FIX_SEGMENT_NUMBER	PROC	NEAR
		;
		;
		;
		ASSUME	ESI:PTR SEGMOD_STRUCT,EDI:PTR SEGMENT_STRUCT
if	fg_pe
		GETT	AL,OUTPUT_PE

		OR	AL,AL
		JZ	L19$

		MOV	ESI,CURN_PEOBJECT_GINDEX
		MOV	EAX,[EDI]._SEG_PEOBJECT_GINDEX

		CMP	ESI,EAX			;PE SECTION #
		JZ	L18$			;SAME SECTION, JUST DO MAX_ALIGN

		TEST	ESI,ESI			;FIRST OBJECT COMING UP!
		JZ	L11$
		;
		;SET MAX ADDRESS FOR LAST PE_SECTION
		;
		CONVERT	ESI,ESI,PE_OBJECT_GARRAY
		ASSUME	ESI:PTR PE_OBJECT_STRUCT

		MOV	EAX,ECX

		DO_FILE_ALIGN_EAX

		MOV	ECX,EAX
		MOV	EBX,PE_BASE

		SUB	ECX,EBX
		MOV	EBX,[ESI]._PEOBJECT_RVA

		SUB	ECX,EBX

		MOV	[ESI]._PEOBJECT_VSIZE,ECX
		;
		;ADJUST FOR BEGINNING OF NEXT SECTION
		;
		CALL	DO_OBJECT_ALIGN

		MOV	ECX,EAX
		JMP	L12$

L18$:
		GETT	AL,OBJECT_FLAGS_DEFINED
		MOV	BL,[EDI]._SEG_32FLAGS

		OR	AL,AL
		JNZ	L185$

		AND	BL,MASK SEG32_NONZERO
		JZ	L185$

		CONVERT	ESI,ESI,PE_OBJECT_GARRAY
		ASSUME	ESI:PTR PE_OBJECT_STRUCT

		JMP	L15$

L11$:
		;
		;FIRST CODE_DATA OBJECT
		;
		MOV	ECX,PE_NEXT_OBJECT_RVA
		MOV	EDX,PE_BASE

		ADD	ECX,EDX
L12$:
		MOV	ESI,[EDI]._SEG_PEOBJECT_GINDEX

		MOV	CURN_PEOBJECT_GINDEX,ESI
		;
		;
		;
		CONVERT	ESI,ESI,PE_OBJECT_GARRAY
		ASSUME	ESI:PTR PE_OBJECT_STRUCT

		MOV	EAX,ECX
		MOV	EBX,PE_BASE

		SUB	EAX,EBX
		XOR	BL,BL

		MOV	[ESI]._PEOBJECT_RVA,EAX
		MOV	AL,[EDI]._SEG_32FLAGS

		RESS	OBJECT_FLAGS_DEFINED,BL
		TEST	AL,MASK SEG32_NONZERO

		JZ	L17$
L15$:
		CALL	FIX_OBJECT_FLAGS
L17$:
L185$:
		MOV	ESI,CURN_SEGMOD_GINDEX
		CONVERT	ESI,ESI,SEGMOD_GARRAY
		ASSUME	ESI:PTR SEGMOD_STRUCT

		JMP	L7$

L19$:
endif

if	fg_segm
		GETT	AL,OUTPUT_SEGMENTED	;DO NOTHING IF DOS OUTPUT
		MOV	EDX,[EDI]._SEG_GROUP_GINDEX

		TEST	AL,AL
		JZ	L5$

		MOV	EAX,SEGMENT_NUMBER
		MOV	EBX,LAST_GROUP_GINDEX

		OR	EDX,EDX
		JZ	FORCE_NEW

		CMP	EBX,EDX
		JZ	USE_OLD

		MOV	LAST_GROUP_GINDEX,EDX
FORCE_NEW:
		INC	EAX			;START OF NEW GROUP, COUNT IT
		XOR	ECX,ECX			;ZERO OUT OFFSET
		MOV	SEGMENT_NUMBER,EAX
USE_OLD:
		MOV	[EDI]._SEG_OS2_NUMBER,EAX
		JMP	L7$
endif

L5$:
		;
		;DOS OUTPUT, IF NOT DOING OVERLAYS, ZERO OUT OFFSET
		;
L7$:
		MOV	AL,[EDI]._SEG_MAX_ALIGN
		CALL	DO_ECX_ALIGN

		XOR	EAX,EAX
		MOV	[EDI]._SEG_OFFSET,ECX		;SET BASE ADDRESS

		MOV	[EDI]._SEG_LEN,EAX
;		MOV	EAX,[EDI]._SEG_SECTION_GINDEX

;		TEST	EAX,EAX
;		JNZ	L9$

;		MOV	EAX,[ESI]._SM_SECTION_GINDEX

;		MOV	[EDI]._SEG_SECTION_GINDEX,EAX
L9$:
		RET

FIX_SEGMENT_NUMBER	ENDP


if	fg_pe


FIX_OBJECT_FLAGS	PROC	NEAR
		;
		;
		;
		ASSUME	ESI:PTR PE_OBJECT_STRUCT,EDI:PTR SEGMENT_STRUCT

		PUSH	EBX
		MOV	EAX,[EDI]._SEG_OS2_FLAGS

		SETT	OBJECT_FLAGS_DEFINED

		TEST	AL,1
		JZ	L1$
		;
		;	DATA
		;
		MOV	EBX,MASK PEL_INIT_DATA_OBJECT + MASK PEH_READABLE

		TEST	EAX,MASK SR_EO_RO
		JNZ	L2$

		OR	EBX,MASK PEH_WRITABLE
		JMP	L2$

L1$:
		;
		;CODE
		;
		MOV	EBX,MASK PEL_CODE_OBJECT + MASK PEH_EXECUTABLE

		TEST	EAX,MASK SR_EO_RO
		JNZ	L2$
		OR	EBX,MASK PEH_READABLE
L2$:
		TEST	EAX,MASK SR_DISCARD
		JZ	L21$
		OR	EBX,MASK PEH_DISCARDABLE
L21$:
		TEST	EAX,MASK SR_SHARED
		JZ	L22$
		OR	EBX,MASK PEH_SHARED
L22$:
		MOV	[ESI]._PEOBJECT_FLAGS,EBX
		POP	EBX

		RET

FIX_OBJECT_FLAGS	ENDP

endif


		.CONST

		ALIGN	4

COM_TABLE	LABEL	DWORD

		DD	0,-1		;CASE 0
		DD	0,-1		;CASE 1
		DD	1,-2		;CASE 2
		DD	15,-16		;CASE 3
		DD	255,-256	;CASE 4
		DD	3,-4		;CASE 5
		DD	4K-1,-(4K)	;CASE 6
		DD	31,-32		;CASE 7	

ALIGN_SEGS_MSG	DB	SIZEOF ALIGN_SEGS_MSG-1,'Defining Segment Addresses',0DH,0AH


		.DATA?

CURN_PEOBJECT_GINDEX	DD	?


		END

